package com.itheima.reggie.controller;

import com.alibaba.dubbo.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 菜品管理(控制器)
 */
@RequestMapping("/dish")
@RestController
@Slf4j
public class DishController {
    /**
     *
     */
    @Autowired
    private DishService dishService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private RedisTemplate redisTemplate;


    //自动注入 service
    @PostMapping
    //post请求
    public R<String>save(@RequestBody DishDto dishDto){
        //传入定义的 展示层与服务层间的数据的DishDto
        log.info("[新增菜品] dish:{}",dishDto);
        //现在已经取得到数据   需要分开存(两张表的信息菜品 和口味)
        //dishService 不能同时保存菜品的基本信息和口味信息
        //  需要自己定义一个方法来保存
        //调用dishService的业务方法  完成菜品的保存
        dishService.saveWithFlavor(dishDto);

       /* 方式一//清理所有的菜品缓存数据
        Set keys=redisTemplate.keys("dish_*");
        //获取到的说有以dish开头的key
        redisTemplate.delete(keys);//删除这些key
        */
       //方式二  仅清理某个分类下面相关联的菜品
        String key="dish_"+dishDto.getCategoryId()+"_1";
        redisTemplate.delete(key);

        return R.success("新增菜品成功");
    }
    /**
     *
     * @param page 当前页码
     * @param pageSize  每页的条数
     * @param name
     * @return
     */
    @GetMapping("/page")
    public R<Page>page(int page,int pageSize,String name){
        log.info("[菜品分页],{},{},{}",page,pageSize,name);
        Page pageInfo = new Page(page,pageSize);
        //根据条件查询 按名字模糊查询  按日期倒叙更新
        LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //LambdaQueryWrapper查询包装器   查询条件是 Dish    穿件一个新到的
        dishLambdaQueryWrapper.like(StringUtils.isNotEmpty(name),Dish::getName,name);
        //新的查询包装器的 Sql 查询  名字不为空   Dish获取名字
        dishLambdaQueryWrapper.orderByDesc(Dish::getUpdateTime);
        //新的查询包装器  按 更新时间  降序排列
        //返回page对象
        dishService.page(pageInfo,dishLambdaQueryWrapper);
        //返回pageInfo
        //存在问题 线上不显示分类的名称 我们也不能直接在是实体类中加入一个属性
        //返回的记录集应该用DishDto替换  因为在DishDto在里面加入分类的名称
        //数据已经在pageInfo的records里面了 (Dish)换成DishDto
        //构建应该page<DishDto>
        Page<DishDto>dishDtoPage=new Page<>();//这个对象视野没有  把PageInfo赋值进来
        //赋值的过程  可以忽略掉不需要的或者目前没必要的属性 (records)
        //pageInfo(page,pageSize,records,total)
        BeanUtils.copyProperties(pageInfo,dishDtoPage,"records");
        //我们需要单独把records里面的Dish换成DishDto
        List<Dish>records=pageInfo.getRecords();
        //遍历这个结果集  把 每条记录换成DishDto  然后把dishDto存入应该根性的列表中
        List<DishDto>dishDtoList=new ArrayList<>();
        for (Dish dish : records) {
            DishDto dishDto=new DishDto();
            BeanUtils.copyProperties(dish,dishDto);
            //当前菜品的分类名称  应该如何获取
            //结论 根据当前菜品的分类Id 通过分类业务对象来获取分类
            Category category= categoryService.getById(dish.getCategoryId());
            dishDto.setCategoryName(category.getName());
            dishDtoList.add(dishDto);
        }
        dishDtoPage.setRecords(dishDtoList);
        return R.success(dishDtoPage);
    }
    /**
     * 修改菜品
     */
    @GetMapping("/{id}")
    public R<DishDto>get(@PathVariable Long id){
        log.info("[根据ID，获取菜品信息],id:{}",id);
        //如果 dishService没有对应的业务  直接返回DishDto 我们需要扩展业务的方法
        DishDto dishDto=dishService.getByIdWithFlavor(id);
        return R.success(dishDto);
    }
    @PutMapping
    public R<String>update(@RequestBody DishDto dishDto){
        log.info("[菜品修改],dto:{}",dishDto);
        //调用Service 的业务方法 完成业务
        //dishService .updateById(DishDto)//知识更新菜品的基本信息
        dishService.updateWithFlavor(dishDto);
        /*方式一//清理所有菜品的缓存数据
        Set keys =redisTemplate.keys("dish_*");
        //获取所有的dish_xxxx开头的key
        redisTemplate.delete(keys);
        //删除这些key*/
        //方式二
        String key="dish_"+dishDto.getCategoryId()+"_1" ;
        redisTemplate.delete(key);
        return R.success("菜品更新成功");
    }
    /**
     * 根据条件查询对应的菜品数据
     * @param dish
     * @return
     */
    /*@GetMapping("/list")
    public R<List<Dish>> list(Dish dish){
        //构造查询条件
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        //new出菜品管理的构造器
        queryWrapper.eq(dish.getCategoryId()!=null,Dish::getCategoryId,dish.getCategoryId());
        //判断获取到的id不为空
        //添加条件  查询状态 是1  为在售
        queryWrapper.eq(Dish::getStatus,1);
        //条件排序的条件
        queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);
        List<Dish> list = dishService.list(queryWrapper);
        return R.success(list);
    }*/
  /*  //套餐保存
    @PostMapping
    public R<String>save (@RequestBody SetmealDto setmealDto){
        log.info("跑通");
        return R.success(null);
    }

*/@Autowired
    private DishFlavorService dishFlavorService;

    @GetMapping("/list")
    public R<List<DishDto>> list(Dish dish){
        /*从缓存中读取数据*/
        List<DishDto>redisDtoList=null;
        String key="dish_"+dish.getCategoryId()+"_"+dish.getStatus();
        redisDtoList= (List<DishDto>) redisTemplate.opsForValue().get(key);
        log.info("redisDtoList:{}", redisDtoList);
        if (redisDtoList!=null){
            log.info("[从缓存读取列表数据]");
            return R.success(redisDtoList);
        }
        //构造查询条件
        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(dish.getCategoryId() != null ,Dish::getCategoryId,dish.getCategoryId());
        //添加条件，查询状态为1（在售状态）的菜品
        queryWrapper.eq(Dish::getStatus,1);
        //添加排序条件
        queryWrapper.orderByAsc(Dish::getSort).orderByDesc(Dish::getUpdateTime);

        List<Dish> list = dishService.list(queryWrapper);

        List<DishDto> dishDtoList = list.stream().map((item) -> {
            DishDto dishDto = new DishDto();
            BeanUtils.copyProperties(item,dishDto);

            Long categoryId = item.getCategoryId();//分类id
            //根据id查询分类对象
            Category category = categoryService.getById(categoryId);
            if(category != null){
                String categoryName = category.getName();
                dishDto.setCategoryName(categoryName);
            }
            //当前菜品的id
            Long dishId = item.getId();
            LambdaQueryWrapper<DishFlavor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(DishFlavor::getDishId,dishId);
            //SQL:select * from dish_flavor where dish_id = ?
            List<DishFlavor> dishFlavorList = dishFlavorService.list(lambdaQueryWrapper);
            dishDto.setFlavors(dishFlavorList);

            return dishDto;
        }).collect(Collectors.toList());
        //如果不存在   需要查询数据库 将禅熏到的数据缓存到Redis//设置过期时间为60 分钟
        redisTemplate.opsForValue().set(key,dishDtoList,60, TimeUnit.MINUTES);

        return R.success(dishDtoList);
    }}
